/*
 * Copyright (c) 2024-2025 LTC-CN. All rights reserved.
 * <p>
 * This file is part of the ltc-cn-springboot project.
 * <p>
 * ltc-cn-springboot is distributed under the terms of the MIT License.
 * For details, see the accompanying LICENSE file or visit:
 * <a href="https://www.ltc-cn.top/projects">...</a>
 */

package top.ltc_cn.minecraft_manager.exception;

import cn.dev33.satoken.exception.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
import top.ltc_cn.springboot_tools.common.LtcResult;
import top.ltc_cn.springboot_tools.enums.LtcResultEnum;

import java.util.Map;

@ControllerAdvice
@Slf4j
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {

    /**
     * 拦截：所有(未知)异常
     */
    @ExceptionHandler(Exception.class)
    public ResponseEntity<LtcResult<?>> handleAllExceptions(Exception ex, WebRequest request) {
        return buildErrorResponse(ex, LtcResultEnum.INTERNAL_SERVER_ERROR, HttpStatus.INTERNAL_SERVER_ERROR);
    }

    /**
     * 拦截：运行时异常
     */
    @ExceptionHandler(RuntimeException.class)
    public ResponseEntity<LtcResult<?>> handleRuntimeExceptions(RuntimeException ex, WebRequest request) {
        return buildErrorResponse(ex, LtcResultEnum.INTERNAL_SERVER_ERROR, HttpStatus.INTERNAL_SERVER_ERROR);
    }

    /**
     * 捕获CaptchaValidationException异常
     */
    @ExceptionHandler(CaptchaValidationException.class)
    public ResponseEntity<LtcResult<?>> handleCaptchaValidationException(CaptchaValidationException ex) {
        log.debug("防水码异常");
        String msg = ex.getMessage();
        if (msg == null){
            msg = LtcResultEnum.TENCENT_CLOUD_CAPTCHA_NEED.getMsg();
        }
        return buildErrorResponse(ex, LtcResult.tencentCloudCaptchaNeed(msg, ex.getParams()), HttpStatus.UNAUTHORIZED);
    }

    /**
     * 拦截：SaTokenException异常
     */
    @ExceptionHandler(SaTokenException.class)
    public ResponseEntity<LtcResult<?>> handleSaTokenExceptions(SaTokenException ex, WebRequest request) {
        return buildErrorResponse(ex, LtcResult.result(ex.getCode(), ex.getMessage()), HttpStatus.INTERNAL_SERVER_ERROR);
    }

    /**
     * 拦截：非法参数异常
     */
    @ExceptionHandler(IllegalArgumentException.class)
    public ResponseEntity<LtcResult<?>> handleIllegalArgumentExceptions(IllegalArgumentException ex, WebRequest request) {
        return buildErrorResponse(ex, LtcResultEnum.BAD_REQUEST, HttpStatus.UNAUTHORIZED);
    }

    /**
     * 拦截：未登录异常
     */
    @ExceptionHandler(NotLoginException.class)
    public ResponseEntity<LtcResult<?>> handlerException(NotLoginException ex) {
        log.debug("未登录异常");
        return buildErrorResponse(ex, LtcResult.unauthorized("未登录"), HttpStatus.UNAUTHORIZED);
    }

    /**
     * 拦截：缺少权限异常
     */
    @ExceptionHandler(NotPermissionException.class)
    public ResponseEntity<LtcResult<?>> handlerException(NotPermissionException ex) {
        log.debug("缺少权限异常：{}", ex.getPermission());
        return buildErrorResponse(ex, LtcResult.unauthorized("缺少权限：" + ex.getPermission()), HttpStatus.UNAUTHORIZED);
    }

    /**
     * 拦截：缺少角色异常
     */
    @ExceptionHandler(NotRoleException.class)
    public ResponseEntity<LtcResult<?>> handlerException(NotRoleException ex) {
        log.debug("缺少角色异常：{}", ex.getRole());
        return buildErrorResponse(ex, LtcResult.unauthorized("缺少角色："+ ex.getRole()), HttpStatus.UNAUTHORIZED);
    }

    /**
     * 拦截：二级认证校验失败异常
     */
    @ExceptionHandler(NotSafeException.class)
    public ResponseEntity<LtcResult<?>> handlerException(NotSafeException ex) {
        log.error("二级身份认证校验失败：{}", ex.getService());
        return buildErrorResponse(ex, LtcResult.unauthorized("二级身份认证校验失败").setCode(4011), HttpStatus.UNAUTHORIZED);
    }

    /**
     * 拦截：服务封禁异常
     */
    @ExceptionHandler(DisableServiceException.class)
    public ResponseEntity<LtcResult<?>> handlerException(DisableServiceException ex) {
        log.warn("服务({})封禁异常", ex.getService());
        Map<String, Object> data = Map.of(
                "level", ex.getLevel(),
                "disableTime", ex.getDisableTime(),
                "service", ex.getService()
        );
        //LtcResult.error("当前账号 " + ex.getService() + " 服务已被封禁 (level=" + ex.getLevel() + ")：" + ex.getDisableTime() + "秒后解封", data)
        return buildErrorResponse(ex, LtcResult.error("当前账号 " + ex.getService() + " 服务已被封禁 (level=" + ex.getLevel() + ")：" + ex.getDisableTime() + "秒后解封", data) , HttpStatus.UNAUTHORIZED);
    }

    /**
     * 拦截：Http Basic 校验失败异常
     */
    @ExceptionHandler(NotHttpBasicAuthException.class)
    public ResponseEntity<LtcResult<?>> handlerException(NotHttpBasicAuthException ex) {
        log.debug("Http Basic 校验失败");
        return buildErrorResponse(ex, LtcResult.unauthorized("Http Basic 校验失败"), HttpStatus.UNAUTHORIZED);
    }

    /**
     * 构建错误响应
     */
    private ResponseEntity<LtcResult<?>> buildErrorResponse(Exception ex, LtcResultEnum resultEnum, HttpStatus httpStatus) {
        log.error("Exception: {}", ex.getMessage(), ex);
        log.warn("该错误被归类为({})返回给客户端", httpStatus.getReasonPhrase());
        LtcResult<?> result = LtcResult.error(resultEnum);
        return new ResponseEntity<>(LtcResult.resultAsData(result, result.getData()), httpStatus);
    }

    /**
     * 构建错误响应
     */
    private ResponseEntity<LtcResult<?>> buildErrorResponse(Exception ex, LtcResult<?> result, HttpStatus httpStatus) {
        log.error("Exception: {}", ex.getMessage(), ex);
        log.warn("该错误被归类为({})返回给客户端", httpStatus.getReasonPhrase());
        return new ResponseEntity<>(LtcResult.resultAsData(result, result.getData()), httpStatus);
    }
}
